using System;
using System.Collections.Generic;
using System.Drawing;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using Habanero.Faces.Base;
using Habanero.Faces.Win;

namespace FireStarterModeller.UI
{
    /// <summary>
    /// This is a control for editing the Properties of a unique constraint via a multi selector.
    /// </summary>
    public class DMUniqueConstraintPropertySelectorControl : UserControlWin, IBOEditorControl
    {
        private DMUniqueConstraint _dmUniqueConstraint;
        private readonly IMultiSelector<DMProperty> _multiSelector;
        private BusinessObjectCollection<DMProperty> _dmProperties;
        private readonly IButtonGroupControl _buttonGroupControl;
        public EventHandler SaveClicked;
        public EventHandler CloseClicked;
        private BusinessObjectCollection<DMUniqueConstraintProperty> _uniqueConstraintProperties;

        public IButtonGroupControl ButtonGroupControl
        {
            get { return _buttonGroupControl; }
        }

        public DMUniqueConstraintPropertySelectorControl(IControlFactory controlFactory)
        {
            if (controlFactory == null) throw new ArgumentNullException("controlFactory");
            _multiSelector = controlFactory.CreateMultiSelector<DMProperty>();
            _buttonGroupControl = controlFactory.CreateButtonGroupControl();
            _buttonGroupControl.AddButton("Close", Close_ClickHandler);
            _buttonGroupControl.AddButton("Cancel", CancelButton_ClickHandler);
            _buttonGroupControl.AddButton("Save", SaveButton_ClickHandler);
            BorderLayoutManager layoutManager = controlFactory.CreateBorderLayoutManager(this);
            layoutManager.AddControl(MultiSelector, BorderLayoutManager.Position.Centre);
            layoutManager.AddControl(_buttonGroupControl, BorderLayoutManager.Position.South);
            MultiSelectorModel<DMProperty> multiSelectorModel = _multiSelector.Model;
            multiSelectorModel.Selected += MultiSelectorSelected;
            multiSelectorModel.Deselected += MultiSelectorDeselected;
            this.MinimumSize = new Size(600, 250);
        }

        private void Close_ClickHandler(object sender, EventArgs e)
        {
            if (this.CloseClicked != null)
            {
                this.CloseClicked(this, new EventArgs());
            }
        }

        private void SaveButton_ClickHandler(object sender, EventArgs e)
        {
            try
            {
                //this.UniqueConstraint.UniqueConstraintProperties.SaveAll();
                _uniqueConstraintProperties.SaveAll();
                if (this.SaveClicked != null)
                {
                    this.SaveClicked(this, new EventArgs());
                }
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        private void CancelButton_ClickHandler(object sender, EventArgs e)
        {
            try
            {
                if (this.UniqueConstraint == null) return;
                //this.UniqueConstraint.UniqueConstraintProperties.CancelCreatedProperties();
                //_uniqueConstraintProperties.CancelCreatedProperties();
                List<DMUniqueConstraintProperty> dmUniqueConstraintProperties =
                    _uniqueConstraintProperties.CreatedBusinessObjects;
                int count = dmUniqueConstraintProperties.Count;
                for (int i = count - 1; i >= 0; i--)
                {
                    DMUniqueConstraintProperty uniqueConstraintProperty = dmUniqueConstraintProperties[i];
                    uniqueConstraintProperty.MarkForDelete();
                    uniqueConstraintProperty.Save();
                }
                LoadMultiselector();
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        private void MultiSelectorDeselected(object sender, MultiSelectorModel<DMProperty>.ModelEventArgs<DMProperty> e)
        {
            try
            {
                //BusinessObjectCollection<DMUniqueConstraintProperty> uniqueConstraintProperties = this.UniqueConstraint.UniqueConstraintProperties;
                foreach (DMUniqueConstraintProperty uniqueConstraintProperty in _uniqueConstraintProperties)
                {
                    if (uniqueConstraintProperty.Property == e.Item)
                    {
                        _uniqueConstraintProperties.MarkForDelete(uniqueConstraintProperty);
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        private void MultiSelectorSelected(object sender, MultiSelectorModel<DMProperty>.ModelEventArgs<DMProperty> e)
        {
            try
            {
                DMUniqueConstraintProperty uniqueConstraintProperty = _uniqueConstraintProperties.CreateBusinessObject();
                uniqueConstraintProperty.Property = e.Item;
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        public DMUniqueConstraint UniqueConstraint
        {
            get { return _dmUniqueConstraint; }
            set
            {
                try
                {
                    _dmUniqueConstraint = value;
                    if (_dmUniqueConstraint == null)
                    {
                        ClearMultiselector();
                    }
                    else
                    {
                        if (this.UniqueConstraint.Class == null)
                        {
                            ClearMultiselector();
                        }
                        else
                        {
                            _dmProperties = this.UniqueConstraint.Class.Properties;
                            SetupCollectionEvents();
                            LoadMultiselector();
                        }
                    }
                }
                catch (Exception ex)
                {
                    GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
                }
            }
        }

        private void LoadMultiselector()
        {
            this.MultiSelector.AllOptions = _dmProperties;
            //BusinessObjectCollection<DMUniqueConstraintProperty> uniqueConstraintProperties = this.UniqueConstraint.UniqueConstraintProperties;
            _uniqueConstraintProperties = this.UniqueConstraint.UniqueConstraintProperties;
            BusinessObjectCollection<DMProperty> selectedProperties = new BusinessObjectCollection<DMProperty>();
            foreach (DMUniqueConstraintProperty uniqueConstraintProperty in _uniqueConstraintProperties)
            {
                selectedProperties.Add(uniqueConstraintProperty.Property);
            }
            this.MultiSelector.SelectedOptions = selectedProperties;
        }

        private void SetupCollectionEvents()
        {
            _dmProperties.BusinessObjectAdded += ((sender, e) =>
                                                  {
                                                      if (this.MultiSelector.Model.AllOptions.Contains(e.BusinessObject))
                                                          return;
                                                      this.MultiSelector.Model.AddOption(e.BusinessObject);
                                                  });
            _dmProperties.BusinessObjectRemoved +=
                ((sender, e) => this.MultiSelector.Model.RemoveOption(e.BusinessObject));
            _dmProperties.BusinessObjectPropertyUpdated += _dmProperties_OnBusinessObjectPropertyUpdated;
        }

        private void _dmProperties_OnBusinessObjectPropertyUpdated(object sender, BOPropUpdatedEventArgs<DMProperty> e)
        {
            if (e.Prop.PropertyName == "PropertyName")
            {
                LoadMultiselector();
            }
        }

        private void ClearMultiselector()
        {
            this.MultiSelector.SelectedOptions.Clear();
            this.MultiSelector.AllOptions.Clear();
        }

        public IMultiSelector<DMProperty> MultiSelector
        {
            get { return _multiSelector; }
        }

        public IBusinessObject BusinessObject
        {
            get { return this.UniqueConstraint; }
            set { this.UniqueConstraint = (DMUniqueConstraint) value; }
        }


        public void DisplayErrors()
        {
        }

        public void ClearErrors()
        {
        }

        #region Implementation of IBOEditorControl

        /// <summary>
        ///             Applies any changes that have occured in any of the Controls on this control's to their related
        ///             Properties on the Business Object.
        /// </summary>
        public void ApplyChangesToBusinessObject()
        {
        }

        /// <summary>
        ///             Does the business object controlled by this control or any of its Aggregate or Composite children have and Errors.
        /// </summary>
        public bool HasErrors
        {
            get { throw new System.NotImplementedException(); }
        }

        /// <summary>
        ///             Does the Business Object controlled by this control or any of its Aggregate or Composite children have and warnings.
        /// </summary>
        public bool HasWarning
        {
            get { throw new System.NotImplementedException(); }
        }

        /// <summary>
        ///              Returns a list of all warnings for the business object controlled by this control or any of its children.
        /// </summary>
        public ErrorList Errors
        {
            get { throw new System.NotImplementedException(); }
        }

        /// <summary>
        ///             Does the business object being managed by this control have any edits that have not been persisted.
        /// </summary>
        /// <returns>
        /// </returns>
        public bool IsDirty
        {
            get { throw new System.NotImplementedException(); }
        }

        /// <summary>
        ///             Returns a list of all warnings for the business object controlled by this control or any of its children.
        /// </summary>
        /// <returns>
        /// </returns>
        public ErrorList Warnings
        {
            get { throw new System.NotImplementedException(); }
        }

        #endregion
    }
}